This notebook outlines my process of generating basic statistical models and exploratory data analysis. This notebook is dependent on the data table gameInfo generated from DataExtraction.RMD.

Packages

library(tidyverse)
Registered S3 methods overwritten by 'dbplyr':
  method         from
  print.tbl_lazy     
  print.tbl_sql      
-- Attaching packages --------------------------------------------------------------------------------- tidyverse 1.3.1 --
v tibble  3.1.2     v dplyr   1.0.7
v tidyr   1.1.3     v stringr 1.4.0
v readr   1.4.0     v forcats 0.5.1
v purrr   0.3.4     
-- Conflicts ------------------------------------------------------------------------------------ tidyverse_conflicts() --
x dplyr::between()   masks data.table::between()
x dplyr::filter()    masks plotly::filter(), stats::filter()
x dplyr::first()     masks data.table::first()
x dplyr::lag()       masks stats::lag()
x dplyr::last()      masks data.table::last()
x purrr::transpose() masks data.table::transpose()
library(sjPlot)
Warning: package ‘sjPlot’ was built under R version 4.1.2
Install package "strengejacke" from GitHub (`devtools::install_github("strengejacke/strengejacke")`) to load all sj-packages at once!
library(plotly)

Empty Lists to Store Results

results <- list(
  models = list(),
  plots = list()
)
data.temp <- list()

Vision Score

Let’s examine the effect of vision score on predicted probability of winning. If the theory is true that controlling vision is integral for winning (which by all intuition it should be) then higher vision score should increase the log odds of victory. ## Just Vision Score

summary(results$models$visionScore)

Call:
glm(formula = win ~ visionScore, family = "binomial", data = gameInfo)

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.9622  -1.1513  -0.2429   1.1914   1.2745  

Coefficients:
              Estimate Std. Error z value Pr(>|z|)    
(Intercept) -0.2254102  0.0040359  -55.85   <2e-16 ***
visionScore  0.0096274  0.0001385   69.50   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 945480  on 682019  degrees of freedom
Residual deviance: 940520  on 682018  degrees of freedom
AIC: 940524

Number of Fisher Scoring iterations: 4
results$plots$visionScore <- plot_model(results$models$visionScore, type = "pred", grid = F)
Data were 'prettified'. Consider using `terms="visionScore [all]"` to get smooth plots.
results$plots$visionScore
$visionScore

So as expected, increasing vision score does appear to increase your chances of victor. So for every point of vision score, the log odds of winning increases by 0.0096 and at a vision score of ~23.4, your win chance is 50%. But what if we wanted to include role (adc, support, etc.)? Is it more important for a particular role to have a high vision score? It should be noted that the average and standard deviation of vision score is 23.49 and 19.96 respectively, so the large vision scores above 100 are very rare and the win rate should not be taken as accurate.

Include Role

results$models$visionScore.role <- glm(win ~ visionScore*individualPosition, family = "binomial", data = gameInfo %>% filter(individualPosition != "Invalid"))

summary(results$models$visionScore.role)

Call:
glm(formula = win ~ visionScore * individualPosition, family = "binomial", 
    data = gameInfo %>% filter(individualPosition != "Invalid"))

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.4343  -1.1539   0.7172   1.1776   1.3968  

Coefficients:
                                       Estimate Std. Error z value Pr(>|z|)    
(Intercept)                          -0.4334489  0.0117634 -36.847  < 2e-16 ***
visionScore                           0.0095649  0.0002294  41.692  < 2e-16 ***
individualPositionBOTTOM              0.0158948  0.0161149   0.986    0.324    
individualPositionMIDDLE             -0.0057545  0.0165318  -0.348    0.728    
individualPositionJUNGLE             -0.0688483  0.0165850  -4.151 3.31e-05 ***
individualPositionTOP                 0.0883103  0.0162263   5.442 5.26e-08 ***
visionScore:individualPositionBOTTOM  0.0149763  0.0005965  25.106  < 2e-16 ***
visionScore:individualPositionMIDDLE  0.0160015  0.0006355  25.178  < 2e-16 ***
visionScore:individualPositionJUNGLE  0.0140470  0.0005503  25.525  < 2e-16 ***
visionScore:individualPositionTOP     0.0122536  0.0006491  18.879  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 943982  on 680939  degrees of freedom
Residual deviance: 934534  on 680930  degrees of freedom
AIC: 934554

Number of Fisher Scoring iterations: 4

As it turns out, having laners / junglers that ward is a very strong indicator of success. If your laners / jungler have a vision score of less than 25, they are actively trolling. Adding time is too big to handle on my local machine - instead I will divide the data into segments and run the individual logistic regressions. I assume since the effect of vision score is near uniform across the non support roles that a model of just the support role and just one other role should be sufficient. ## Include Game Time

summary(results$models$visionScore.time.support)

Call:
glm(formula = win ~ visionScore * timePlayed, family = "binomial", 
    data = gameInfo %>% filter(individualPosition == "UTILITY"))

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-1.9891  -1.1543   0.7182   1.1475   1.8167  

Coefficients:
                         Estimate Std. Error z value Pr(>|z|)    
(Intercept)            -1.931e-01  3.436e-02  -5.619 1.92e-08 ***
visionScore             3.455e-02  8.837e-04  39.096  < 2e-16 ***
timePlayed             -2.301e-02  1.332e-03 -17.276  < 2e-16 ***
visionScore:timePlayed -5.150e-04  2.558e-05 -20.135  < 2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 188422  on 135917  degrees of freedom
Residual deviance: 184589  on 135914  degrees of freedom
AIC: 184597

Number of Fisher Scoring iterations: 4

Constructing a Table to Plot Logistic Regression Surface

Function to Generate Data in the Format Required by Plotly

data.temp$visionScore <- expand_grid(
    visionScore = seq(min(gameInfo$visionScore), mean(gameInfo$visionScore) + 4*sd(gameInfo$visionScore), length.out = 50),
    timePlayed = seq(5, 60, length.out = 50)
  ) 

GET_SURFACE <- function(MODEL, TABLE = data.temp$visionScore){
  
  table.temp <- TABLE %>% 
    mutate(
      p_win = 1-exp(MODEL$coefficients[[1]]  + MODEL$coefficients[[2]]*visionScore + MODEL$coefficients[[3]]*timePlayed + MODEL$coefficients[[4]]*visionScore*timePlayed)/(1 + exp(MODEL$coefficients[[1]]  + MODEL$coefficients[[2]]*visionScore + MODEL$coefficients[[3]]*timePlayed + MODEL$coefficients[[4]]*visionScore*timePlayed)
      )
    )
  
  output.raw <- list()
  
  for(i in 0:49){
    
    output.raw[[i+1]] <- table.temp$p_win[(50*i+1):((i+1)*50)]
    
  }
  
  output <- rbind(output.raw[1:50]) %>% 
    return()
  
}

data.temp$visionScore.support <- GET_SURFACE(results$models$visionScore.time.support)
data.temp$visionScore.nonSupport <- GET_SURFACE(results$models$visionScore.time.nonSupport)
results$plots$visionScore.time.support <- plot_ly(
  x = seq(min(gameInfo$visionScore), mean(gameInfo$visionScore) + 4*sd(gameInfo$visionScore), length.out = 50),
  y = seq(5, 60, length.out = 50),
  z = data.temp$visionScore.support,
  type = "surface"
) %>% 
  layout(
    scene = list(
      xaxis = list(title = "Vision Score"),
      yaxis = list(title = "Game Time (Mins)"),
      zaxis = list(title = "Probability of winning")
    )
  )

results$plots$visionScore.time.support
results$plots$visionScore.time.nonSupport <- plot_ly(
  x = seq(min(gameInfo$visionScore), mean(gameInfo$visionScore) + 4*sd(gameInfo$visionScore), length.out = 50),
  y = seq(5, 60, length.out = 50),
  z = data.temp$visionScore.nonSupport,
  type = "surface"
) %>% 
  layout(
    scene = list(
      xaxis = list(title = "Vision Score"),
      yaxis = list(title = "Game Time (Mins)"),
      zaxis = list(title = "Probability of winning")
    )
  )

results$plots$visionScore.time.nonSupport

Calculating the Contour of 50% Win Rate

data.temp$contour.visionScore.support <- tibble(gameTime = 1:12*5) %>% 
  mutate(visionScore = (-results$models$visionScore.time.support$coefficients[[1]]-results$models$visionScore.time.support$coefficients[[3]]*gameTime)/(results$models$visionScore.time.support$coefficients[[2]] + results$models$visionScore.time.support$coefficients[[4]]*gameTime))
data.temp$contour.visionScore.nonSupport <- tibble(gameTime = 1:12*5) %>% 
  mutate(visionScore = (-results$models$visionScore.time.nonSupport$coefficients[[1]]-results$models$visionScore.time.nonSupport$coefficients[[3]]*gameTime)/(results$models$visionScore.time.nonSupport$coefficients[[2]] + results$models$visionScore.time.nonSupport$coefficients[[4]]*gameTime))

data.temp$contour.visionScore.support
data.temp$contour.visionScore.nonSupport

So for a support, you want your vision score to be around 25 at 20 minutes, 45 at 30 minutes, and 80 at 40 minutes to have a 50% chance of winning. For a non-support, you want your vision score to be around 10 at 20 minutes, 20 at 30 minutes, and 30 at 40 minutes.

Gold Percentage by Position

It’s a common idea that the ADC role has been considered useless for this season - let’s see what the data has to say about that!

data.temp$goldPercent <- gameInfo %>% 
  group_by(match, win) %>% # here win is just used to group team
  mutate(team_gold = sum(goldEarned), goldEarned = goldEarned / team_gold) %>% 
  ungroup()

results$models$goldPercent <- glm(win ~ goldEarned*individualPosition, data = data.temp$goldPercent %>% filter(individualPosition != "Invalid"), family = "binomial")

summary(results$models$goldPercent)

Call:
glm(formula = win ~ goldEarned * individualPosition, family = "binomial", 
    data = data.temp$goldPercent %>% filter(individualPosition != 
        "Invalid"))

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.323  -1.180   1.097   1.175   1.460  

Coefficients:
                                    Estimate Std. Error z value Pr(>|z|)    
(Intercept)                          0.59312    0.03422   17.34   <2e-16 ***
goldEarned                          -3.73638    0.21356  -17.50   <2e-16 ***
individualPositionBOTTOM            -0.95585    0.04898  -19.52   <2e-16 ***
individualPositionMIDDLE            -0.52590    0.04799  -10.96   <2e-16 ***
individualPositionJUNGLE            -0.59060    0.04850  -12.18   <2e-16 ***
individualPositionTOP               -0.59217    0.04729  -12.52   <2e-16 ***
goldEarned:individualPositionBOTTOM  5.47693    0.26768   20.46   <2e-16 ***
goldEarned:individualPositionMIDDLE  3.43901    0.26587   12.94   <2e-16 ***
goldEarned:individualPositionJUNGLE  3.67854    0.26801   13.72   <2e-16 ***
goldEarned:individualPositionTOP     3.76405    0.26362   14.28   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 943982  on 680939  degrees of freedom
Residual deviance: 943546  on 680930  degrees of freedom
AIC: 943566

Number of Fisher Scoring iterations: 3

So it would appear that having your carry fed is actually a very strong indicator of win percentage. So why might people believe that ADC is useless? Let’s add tier as a covariate and see what we see. (Also as a note, winrate drops off a cliff if support steals all the gold so good to know…as a support main) ## Add tier

summary(results$models$goldPercent.tier)

Call:
glm(formula = win ~ goldEarned * individualPosition * tier, family = "binomial", 
    data = goldPercent %>% filter(individualPosition != "Invalid"))

Deviance Residuals: 
   Min      1Q  Median      3Q     Max  
-1.346  -1.179   1.081   1.176   1.492  

Coefficients:
                                                   Estimate Std. Error z value Pr(>|z|)    
(Intercept)                                       0.7540872  0.0900390   8.375  < 2e-16 ***
goldEarned                                       -4.4437284  0.5216559  -8.519  < 2e-16 ***
individualPositionBOTTOM                         -0.9870719  0.1257502  -7.849 4.18e-15 ***
individualPositionMIDDLE                         -0.8395340  0.1217085  -6.898 5.28e-12 ***
individualPositionJUNGLE                         -0.7553173  0.1208626  -6.249 4.12e-10 ***
individualPositionTOP                            -0.6528942  0.1213688  -5.379 7.47e-08 ***
tierBRONZE                                        0.0008867  0.1291223   0.007 0.994521    
tierSILVER                                       -0.0263694  0.1248695  -0.211 0.832750    
tierGOLD                                         -0.1054959  0.1243836  -0.848 0.396355    
tierPLATINUM                                     -0.3440531  0.1275268  -2.698 0.006978 ** 
tierDIAMOND                                      -0.2099257  0.1221066  -1.719 0.085578 .  
goldEarned:individualPositionBOTTOM               5.7346544  0.6640271   8.636  < 2e-16 ***
goldEarned:individualPositionMIDDLE               4.9490595  0.6498041   7.616 2.61e-14 ***
goldEarned:individualPositionJUNGLE               4.2850081  0.6474130   6.619 3.62e-11 ***
goldEarned:individualPositionTOP                  4.0531294  0.6476428   6.258 3.89e-10 ***
goldEarned:tierBRONZE                            -0.0849957  0.7565685  -0.112 0.910551    
goldEarned:tierSILVER                            -0.0440435  0.7426111  -0.059 0.952706    
goldEarned:tierGOLD                               0.3153522  0.7529545   0.419 0.675348    
goldEarned:tierPLATINUM                           1.7835490  0.7827785   2.278 0.022698 *  
goldEarned:tierDIAMOND                            0.8439319  0.7536048   1.120 0.262773    
individualPositionBOTTOM:tierBRONZE               0.1114395  0.1799761   0.619 0.535791    
individualPositionMIDDLE:tierBRONZE              -0.0803993  0.1743837  -0.461 0.644764    
individualPositionJUNGLE:tierBRONZE               0.2750908  0.1755888   1.567 0.117191    
individualPositionTOP:tierBRONZE                 -0.3524101  0.1741484  -2.024 0.043009 *  
individualPositionBOTTOM:tierSILVER              -0.1903623  0.1751922  -1.087 0.277218    
individualPositionMIDDLE:tierSILVER               0.1201389  0.1700873   0.706 0.479979    
individualPositionJUNGLE:tierSILVER               0.1484385  0.1716677   0.865 0.387212    
individualPositionTOP:tierSILVER                 -0.1245770  0.1693526  -0.736 0.461970    
individualPositionBOTTOM:tierGOLD                -0.1700483  0.1748046  -0.973 0.330657    
individualPositionMIDDLE:tierGOLD                 0.4676913  0.1704174   2.744 0.006062 ** 
individualPositionJUNGLE:tierGOLD                 0.0560445  0.1712902   0.327 0.743524    
individualPositionTOP:tierGOLD                   -0.0845517  0.1686760  -0.501 0.616183    
individualPositionBOTTOM:tierPLATINUM             0.2230046  0.1782083   1.251 0.210799    
individualPositionMIDDLE:tierPLATINUM             0.5272124  0.1748173   3.016 0.002563 ** 
individualPositionJUNGLE:tierPLATINUM             0.3151809  0.1752976   1.798 0.072181 .  
individualPositionTOP:tierPLATINUM                0.3442697  0.1722330   1.999 0.045623 *  
individualPositionBOTTOM:tierDIAMOND             -0.0390518  0.1700383  -0.230 0.818352    
individualPositionMIDDLE:tierDIAMOND              0.5486186  0.1666078   3.293 0.000992 ***
individualPositionJUNGLE:tierDIAMOND             -0.0196129  0.1661978  -0.118 0.906060    
individualPositionTOP:tierDIAMOND                 0.2649390  0.1641395   1.614 0.106504    
goldEarned:individualPositionBOTTOM:tierBRONZE   -0.5410284  0.9565154  -0.566 0.571649    
goldEarned:individualPositionMIDDLE:tierBRONZE    0.4059998  0.9374082   0.433 0.664936    
goldEarned:individualPositionJUNGLE:tierBRONZE   -1.1519592  0.9454214  -1.218 0.223049    
goldEarned:individualPositionTOP:tierBRONZE       1.7324872  0.9367984   1.849 0.064404 .  
goldEarned:individualPositionBOTTOM:tierSILVER    0.8976081  0.9371119   0.958 0.338141    
goldEarned:individualPositionMIDDLE:tierSILVER   -0.4794273  0.9214764  -0.520 0.602867    
goldEarned:individualPositionJUNGLE:tierSILVER   -0.4136301  0.9304532  -0.445 0.656647    
goldEarned:individualPositionTOP:tierSILVER       0.7022446  0.9185403   0.765 0.444556    
goldEarned:individualPositionBOTTOM:tierGOLD      0.7741899  0.9440787   0.820 0.412189    
goldEarned:individualPositionMIDDLE:tierGOLD     -2.1321757  0.9320332  -2.288 0.022157 *  
goldEarned:individualPositionJUNGLE:tierGOLD      0.0625770  0.9376650   0.067 0.946791    
goldEarned:individualPositionTOP:tierGOLD         0.5259145  0.9252041   0.568 0.569743    
goldEarned:individualPositionBOTTOM:tierPLATINUM -1.4223405  0.9719356  -1.463 0.143355    
goldEarned:individualPositionMIDDLE:tierPLATINUM -2.7415891  0.9644264  -2.843 0.004473 ** 
goldEarned:individualPositionJUNGLE:tierPLATINUM -1.4908005  0.9668010  -1.542 0.123075    
goldEarned:individualPositionTOP:tierPLATINUM    -1.8674175  0.9549370  -1.956 0.050519 .  
goldEarned:individualPositionBOTTOM:tierDIAMOND   0.1081900  0.9315740   0.116 0.907544    
goldEarned:individualPositionMIDDLE:tierDIAMOND  -2.5436799  0.9238311  -2.753 0.005898 ** 
goldEarned:individualPositionJUNGLE:tierDIAMOND   0.3662858  0.9206385   0.398 0.690733    
goldEarned:individualPositionTOP:tierDIAMOND     -1.1915075  0.9152201  -1.302 0.192957    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 943982  on 680939  degrees of freedom
Residual deviance: 943423  on 680880  degrees of freedom
AIC: 943543

Number of Fisher Scoring iterations: 3

Results are unclear, for lower elo’s in general, gold percentage is less important on ADC but it’s not super clear based on the the variance in Silver and Platinum. Interestingly, jungle seems to be more of a carry role in higher elos. Might be because of the champion choice. This will be examined later.

Total Damage Done

summary(results$models$damageDoneChamp)

Call:
glm(formula = win ~ totalDamageDealtToChampions * individualPosition, 
    family = "binomial", data = gameInfo %>% filter(individualPosition != 
        "Invalid"))

Deviance Residuals: 
    Min       1Q   Median       3Q      Max  
-2.5621  -1.1437   0.6297   1.1823   1.4300  

Coefficients:
                                                       Estimate Std. Error z value Pr(>|z|)    
(Intercept)                                          -1.946e-01  9.132e-03  -21.31   <2e-16 ***
totalDamageDealtToChampions                           1.711e-05  6.419e-07   26.66   <2e-16 ***
individualPositionBOTTOM                             -3.756e-01  1.428e-02  -26.30   <2e-16 ***
individualPositionMIDDLE                             -3.821e-01  1.459e-02  -26.18   <2e-16 ***
individualPositionJUNGLE                             -2.814e-01  1.389e-02  -20.26   <2e-16 ***
individualPositionTOP                                -3.024e-01  1.452e-02  -20.82   <2e-16 ***
totalDamageDealtToChampions:individualPositionBOTTOM  1.429e-05  8.256e-07   17.31   <2e-16 ***
totalDamageDealtToChampions:individualPositionMIDDLE  1.244e-05  8.207e-07   15.16   <2e-16 ***
totalDamageDealtToChampions:individualPositionJUNGLE  1.123e-05  8.450e-07   13.29   <2e-16 ***
totalDamageDealtToChampions:individualPositionTOP     1.019e-05  8.384e-07   12.15   <2e-16 ***
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 943982  on 680939  degrees of freedom
Residual deviance: 930273  on 680930  degrees of freedom
AIC: 930293

Number of Fisher Scoring iterations: 4
results$plots$damageDoneChamp <- plot_model(damageDoneChamp.fit, type = "int")
Data were 'prettified'. Consider using `terms="totalDamageDealtToChampions [all]"` to get smooth plots.
results$plots$damageDoneChamp

Not much difference based on whoever does damage to champion aside from support. ## Average Total Damage and Damage to Champions based on Role

data.temp$damageDone <- gameInfo %>% 
  filter(individualPosition != "Invalid") %>% 
  select(individualPosition, totalDamageDealtToChampions, totalDamageDealt)
data.temp$damageDone %>% 
  ggplot(aes(x = individualPosition, y = totalDamageDealt)) +
  geom_boxplot()

data.temp$damageDone %>%  
  ggplot(aes(x = individualPosition, y = totalDamageDealtToChampions)) +
  geom_boxplot()

data.temp$damageDone %>% 
  filter(individualPosition != "Invalid") %>% 
  group_by(individualPosition) %>% 
  summarize(avg_damage_champ = mean(totalDamageDealtToChampions), avg_damage_total = mean(totalDamageDealt))

Kruskal-Wallis Test

kruskal.test(totalDamageDealt~individualPosition, data = data.temp$damageDone)

    Kruskal-Wallis rank sum test

data:  totalDamageDealt by individualPosition
Kruskal-Wallis chi-squared = 245961, df = 4, p-value < 2.2e-16
pairwise.wilcox.test(data.temp$damageDone$totalDamageDealt, data.temp$damageDone$individualPosition, p.adjust.method = "fdr")

    Pairwise comparisons using Wilcoxon rank sum test with continuity correction 

data:  data.temp$damageDone$totalDamageDealt and data.temp$damageDone$individualPosition 

       UTILITY BOTTOM  MIDDLE  JUNGLE 
BOTTOM < 2e-16 -       -       -      
MIDDLE < 2e-16 < 2e-16 -       -      
JUNGLE < 2e-16 < 2e-16 < 2e-16 -      
TOP    < 2e-16 4.3e-07 < 2e-16 < 2e-16

P value adjustment method: fdr 

Not really useful, sample size is so large which makes any small difference significant. Visual analysis of boxplots probably more useful.

Champion Difficulty

data.temp$championDifficulty <- gameInfo %>% 
  left_join(
    champions.scraped %>% 
      select(name, difficulty),
    by = c("championName" = "name")
  ) %>% 
  filter(!is.na(difficulty))

results$models$championDifficulty <- glm(win ~ difficulty*tier, data = data.temp$championDifficulty, family = "binomial")

summary(results$models$championDifficulty)

Call:
glm(formula = win ~ difficulty * tier, family = "binomial", data = data.temp$championDifficulty)

Deviance Residuals: 
     Min        1Q    Median        3Q       Max  
-1.19278  -1.17777   0.00661   1.17705   1.20620  

Coefficients:
                                 Estimate Std. Error z value Pr(>|z|)    
(Intercept)                     0.0268696  0.0102058   2.633  0.00847 ** 
difficultyAverage              -0.0437489  0.0174334  -2.509  0.01209 *  
difficultyHard                 -0.0290928  0.0211231  -1.377  0.16842    
difficultySevere               -0.0911225  0.0221172  -4.120 3.79e-05 ***
tierBRONZE                      0.0092404  0.0142805   0.647  0.51759    
tierSILVER                      0.0016172  0.0137644   0.117  0.90647    
tierGOLD                       -0.0044844  0.0137115  -0.327  0.74363    
tierPLATINUM                   -0.0068397  0.0141503  -0.483  0.62884    
tierDIAMOND                    -0.0053488  0.0135708  -0.394  0.69348    
difficultyAverage:tierBRONZE    0.0024604  0.0242620   0.101  0.91923    
difficultyHard:tierBRONZE      -0.0443339  0.0291447  -1.521  0.12822    
difficultySevere:tierBRONZE    -0.0124684  0.0301496  -0.414  0.67920    
difficultyAverage:tierSILVER    0.0161154  0.0230530   0.699  0.48452    
difficultyHard:tierSILVER      -0.0124918  0.0273823  -0.456  0.64825    
difficultySevere:tierSILVER    -0.0001723  0.0282654  -0.006  0.99514    
difficultyAverage:tierGOLD      0.0219788  0.0226007   0.972  0.33081    
difficultyHard:tierGOLD         0.0013287  0.0264725   0.050  0.95997    
difficultySevere:tierGOLD       0.0240251  0.0275498   0.872  0.38318    
difficultyAverage:tierPLATINUM  0.0294448  0.0229928   1.281  0.20033    
difficultyHard:tierPLATINUM     0.0152147  0.0264962   0.574  0.56582    
difficultySevere:tierPLATINUM   0.0211271  0.0275086   0.768  0.44248    
difficultyAverage:tierDIAMOND   0.0181623  0.0219523   0.827  0.40804    
difficultyHard:tierDIAMOND      0.0080260  0.0252925   0.317  0.75099    
difficultySevere:tierDIAMOND    0.0392715  0.0264616   1.484  0.13778    
---
Signif. codes:  0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

(Dispersion parameter for binomial family taken to be 1)

    Null deviance: 945480  on 682019  degrees of freedom
Residual deviance: 945352  on 681996  degrees of freedom
AIC: 945400

Number of Fisher Scoring iterations: 3
results$plots$championDifficulty <- plot_model(results$models$championDifficulty, type = "int")

results$plots$championDifficulty

Hard to say - I might have expected that win rate of difficult champions would increase when we get to higher ranks. Difficulty however, does not take into account meta and other interactions. The model generated doesn’t have the greatest significance so interpretability is limited. It is striking however, the general trend of winrate decreasing with the increase of champion difficulty. Maybe if we interpret difficulty as an ordinal variable we might see a significant linear regression model.

A soft takeaway then is play easier champions…at least easier as defined by mobalytics.

LS0tDQp0aXRsZTogIkJhc2ljIFN0YXRpc3RpY2FsIE1vZGVscyINCm91dHB1dDogaHRtbF9ub3RlYm9vaw0KLS0tDQoNClRoaXMgbm90ZWJvb2sgb3V0bGluZXMgbXkgcHJvY2VzcyBvZiBnZW5lcmF0aW5nIGJhc2ljIHN0YXRpc3RpY2FsIG1vZGVscyBhbmQgZXhwbG9yYXRvcnkgZGF0YSBhbmFseXNpcy4gVGhpcyBub3RlYm9vayBpcyBkZXBlbmRlbnQgb24gdGhlIGRhdGEgdGFibGUgZ2FtZUluZm8gZ2VuZXJhdGVkIGZyb20gRGF0YUV4dHJhY3Rpb24uUk1ELg0KDQojIFBhY2thZ2VzDQpgYGB7cn0NCmxpYnJhcnkodGlkeXZlcnNlKQ0KbGlicmFyeShzalBsb3QpDQpsaWJyYXJ5KHBsb3RseSkNCmBgYA0KDQojIEVtcHR5IExpc3RzIHRvIFN0b3JlIFJlc3VsdHMNCmBgYHtyfQ0KIyBEb24ndCBydW4gdGhpcyBhZ2FpbiBvciBlbHNlIHlvdSdsbCBjbGVhciB0aGUgZGF0YSwgY29tbWVudGVkIG91dCB0byBhdm9pZCB0aGlzIHByb2JsZW0gOjwNCiMgcmVzdWx0cyA8LSBsaXN0KA0KIyAgIG1vZGVscyA9IGxpc3QoKSwNCiMgICBwbG90cyA9IGxpc3QoKQ0KIyApDQpgYGANCg0KIyBWaXNpb24gU2NvcmUNCkxldCdzIGV4YW1pbmUgdGhlIGVmZmVjdCBvZiB2aXNpb24gc2NvcmUgb24gcHJlZGljdGVkIHByb2JhYmlsaXR5IG9mIHdpbm5pbmcuIElmIHRoZSB0aGVvcnkgaXMgdHJ1ZSB0aGF0IGNvbnRyb2xsaW5nIHZpc2lvbiBpcyBpbnRlZ3JhbCBmb3Igd2lubmluZyAod2hpY2ggYnkgYWxsIGludHVpdGlvbiBpdCBzaG91bGQgYmUpIHRoZW4gaGlnaGVyIHZpc2lvbiBzY29yZSBzaG91bGQgaW5jcmVhc2UgdGhlIGxvZyBvZGRzIG9mIHZpY3RvcnkuDQojIyBKdXN0IFZpc2lvbiBTY29yZQ0KYGBge3J9DQpyZXN1bHRzJG1vZGVscyR2aXNpb25TY29yZSA8LSBnbG0od2luIH4gdmlzaW9uU2NvcmUsIGZhbWlseSA9ICJiaW5vbWlhbCIsIGRhdGEgPSBnYW1lSW5mbykNCg0Kc3VtbWFyeShyZXN1bHRzJG1vZGVscyR2aXNpb25TY29yZSkNCmBgYA0KYGBge3J9DQpyZXN1bHRzJHBsb3RzJHZpc2lvblNjb3JlIDwtIHBsb3RfbW9kZWwocmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUsIHR5cGUgPSAicHJlZCIsIGdyaWQgPSBGKQ0KDQpyZXN1bHRzJHBsb3RzJHZpc2lvblNjb3JlDQpgYGANClNvIGFzIGV4cGVjdGVkLCBpbmNyZWFzaW5nIHZpc2lvbiBzY29yZSAqZG9lcyogYXBwZWFyIHRvIGluY3JlYXNlIHlvdXIgY2hhbmNlcyBvZiB2aWN0b3IuIFNvIGZvciBldmVyeSBwb2ludCBvZiB2aXNpb24gc2NvcmUsIHRoZSBsb2cgb2RkcyBvZiB3aW5uaW5nIGluY3JlYXNlcyBieSAwLjAwOTYgYW5kIGF0IGEgdmlzaW9uIHNjb3JlIG9mIH4yMy40LCB5b3VyIHdpbiBjaGFuY2UgaXMgNTAlLiBCdXQgd2hhdCBpZiB3ZSB3YW50ZWQgdG8gaW5jbHVkZSByb2xlIChhZGMsIHN1cHBvcnQsIGV0Yy4pPyBJcyBpdCBtb3JlIGltcG9ydGFudCBmb3IgYSBwYXJ0aWN1bGFyIHJvbGUgdG8gaGF2ZSBhIGhpZ2ggdmlzaW9uIHNjb3JlPyBJdCBzaG91bGQgYmUgbm90ZWQgdGhhdCB0aGUgYXZlcmFnZSBhbmQgc3RhbmRhcmQgZGV2aWF0aW9uIG9mIHZpc2lvbiBzY29yZSBpcyAyMy40OSBhbmQgMTkuOTYgcmVzcGVjdGl2ZWx5LCBzbyB0aGUgbGFyZ2UgdmlzaW9uIHNjb3JlcyBhYm92ZSAxMDAgYXJlIHZlcnkgcmFyZSBhbmQgdGhlIHdpbiByYXRlIHNob3VsZCBub3QgYmUgdGFrZW4gYXMgYWNjdXJhdGUuDQoNCiMjIEluY2x1ZGUgUm9sZQ0KYGBge3J9DQpyZXN1bHRzJG1vZGVscyR2aXNpb25TY29yZS5yb2xlIDwtIGdsbSh3aW4gfiB2aXNpb25TY29yZSppbmRpdmlkdWFsUG9zaXRpb24sIGZhbWlseSA9ICJiaW5vbWlhbCIsIGRhdGEgPSBnYW1lSW5mby5ub0ludmFsaWQpDQoNCnN1bW1hcnkocmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUucm9sZSkNCmBgYA0KYGBge3J9DQpyZXN1bHRzJHBsb3RzJHZpc2lvblNjb3JlLnJvbGUgPC0gcGxvdF9tb2RlbChyZXN1bHRzJG1vZGVscyR2aXNpb25TY29yZS5yb2xlLCB0eXBlID0gImludCIpDQoNCnJlc3VsdHMkcGxvdHMkdmlzaW9uU2NvcmUucm9sZQ0KYGBgDQpBcyBpdCB0dXJucyBvdXQsIGhhdmluZyBsYW5lcnMgLyBqdW5nbGVycyB0aGF0IHdhcmQgaXMgYSB2ZXJ5IHN0cm9uZyBpbmRpY2F0b3Igb2Ygc3VjY2Vzcy4gSWYgeW91ciBsYW5lcnMgLyBqdW5nbGVyIGhhdmUgYSB2aXNpb24gc2NvcmUgb2YgbGVzcyB0aGFuIDI1LCB0aGV5IGFyZSAqYWN0aXZlbHkqIHRyb2xsaW5nLiBBZGRpbmcgdGltZSBpcyB0b28gYmlnIHRvIGhhbmRsZSBvbiBteSBsb2NhbCBtYWNoaW5lIC0gaW5zdGVhZCBJIHdpbGwgZGl2aWRlIHRoZSBkYXRhIGludG8gc2VnbWVudHMgYW5kIHJ1biB0aGUgaW5kaXZpZHVhbCBsb2dpc3RpYyByZWdyZXNzaW9ucy4gSSBhc3N1bWUgc2luY2UgdGhlIGVmZmVjdCBvZiB2aXNpb24gc2NvcmUgaXMgbmVhciB1bmlmb3JtIGFjcm9zcyB0aGUgbm9uIHN1cHBvcnQgcm9sZXMgdGhhdCBhIG1vZGVsIG9mIGp1c3QgdGhlIHN1cHBvcnQgcm9sZSBhbmQganVzdCBvbmUgb3RoZXIgcm9sZSBzaG91bGQgYmUgc3VmZmljaWVudC4NCiMjIEluY2x1ZGUgR2FtZSBUaW1lDQpgYGB7cn0NCnJlc3VsdHMkbW9kZWxzJHZpc2lvblNjb3JlLnRpbWUuc3VwcG9ydCA8LSBnbG0od2luIH4gdmlzaW9uU2NvcmUqdGltZVBsYXllZCwgZGF0YSA9IGdhbWVJbmZvICU+JSBmaWx0ZXIoaW5kaXZpZHVhbFBvc2l0aW9uID09ICJVVElMSVRZIiksIGZhbWlseSA9ICJiaW5vbWlhbCIpDQoNCnJlc3VsdHMkbW9kZWxzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydCA8LSBnbG0od2luIH4gdmlzaW9uU2NvcmUqdGltZVBsYXllZCwgZGF0YSA9IGdhbWVJbmZvICU+JSBmaWx0ZXIoaW5kaXZpZHVhbFBvc2l0aW9uID09ICJCT1RUT00iKSwgZmFtaWx5ID0gImJpbm9taWFsIikNCg0Kc3VtbWFyeShyZXN1bHRzJG1vZGVscyR2aXNpb25TY29yZS50aW1lLnN1cHBvcnQpDQpzdW1tYXJ5KHJlc3VsdHMkbW9kZWxzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydCkNCmBgYA0KIyMgQ29uc3RydWN0aW5nIGEgVGFibGUgdG8gUGxvdCBMb2dpc3RpYyBSZWdyZXNzaW9uIFN1cmZhY2UNCiMjIyBGdW5jdGlvbiB0byBHZW5lcmF0ZSBEYXRhIGluIHRoZSBGb3JtYXQgUmVxdWlyZWQgYnkgUGxvdGx5DQpgYGB7cn0NCmRhdGEudGVtcCR2aXNpb25TY29yZSA8LSBleHBhbmRfZ3JpZCgNCiAgICB2aXNpb25TY29yZSA9IHNlcShtaW4oZ2FtZUluZm8kdmlzaW9uU2NvcmUpLCBtZWFuKGdhbWVJbmZvJHZpc2lvblNjb3JlKSArIDQqc2QoZ2FtZUluZm8kdmlzaW9uU2NvcmUpLCBsZW5ndGgub3V0ID0gNTApLA0KICAgIHRpbWVQbGF5ZWQgPSBzZXEoNSwgNjAsIGxlbmd0aC5vdXQgPSA1MCkNCiAgKSANCg0KIyBORVhUIFRJTUUgVVNFIFRIRSBPVVRFUiBGVU5DVElPTiBCVVQgT0sNCkdFVF9TVVJGQUNFIDwtIGZ1bmN0aW9uKE1PREVMLCBUQUJMRSA9IGRhdGEudGVtcCR2aXNpb25TY29yZSl7DQogIA0KICB0YWJsZS50ZW1wIDwtIFRBQkxFICU+JSANCiAgICBtdXRhdGUoDQogICAgICBwX3dpbiA9IDEtZXhwKE1PREVMJGNvZWZmaWNpZW50c1tbMV1dICArIE1PREVMJGNvZWZmaWNpZW50c1tbMl1dKnZpc2lvblNjb3JlICsgTU9ERUwkY29lZmZpY2llbnRzW1szXV0qdGltZVBsYXllZCArIE1PREVMJGNvZWZmaWNpZW50c1tbNF1dKnZpc2lvblNjb3JlKnRpbWVQbGF5ZWQpLygxICsgZXhwKE1PREVMJGNvZWZmaWNpZW50c1tbMV1dICArIE1PREVMJGNvZWZmaWNpZW50c1tbMl1dKnZpc2lvblNjb3JlICsgTU9ERUwkY29lZmZpY2llbnRzW1szXV0qdGltZVBsYXllZCArIE1PREVMJGNvZWZmaWNpZW50c1tbNF1dKnZpc2lvblNjb3JlKnRpbWVQbGF5ZWQpDQogICAgICApDQogICAgKQ0KICANCiAgb3V0cHV0LnJhdyA8LSBsaXN0KCkNCiAgDQogIGZvcihpIGluIDA6NDkpew0KICAgIA0KICAgIG91dHB1dC5yYXdbW2krMV1dIDwtIHRhYmxlLnRlbXAkcF93aW5bKDUwKmkrMSk6KChpKzEpKjUwKV0NCiAgICANCiAgfQ0KICANCiAgb3V0cHV0IDwtIHJiaW5kKG91dHB1dC5yYXdbMTo1MF0pICU+JSANCiAgICByZXR1cm4oKQ0KICANCn0NCg0KZGF0YS50ZW1wJHZpc2lvblNjb3JlLnN1cHBvcnQgPC0gR0VUX1NVUkZBQ0UocmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUudGltZS5zdXBwb3J0KQ0KZGF0YS50ZW1wJHZpc2lvblNjb3JlLm5vblN1cHBvcnQgPC0gR0VUX1NVUkZBQ0UocmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUudGltZS5ub25TdXBwb3J0KQ0KYGBgDQoNCmBgYHtyfQ0KcmVzdWx0cyRwbG90cyR2aXNpb25TY29yZS50aW1lLnN1cHBvcnQgPC0gcGxvdF9seSgNCiAgeCA9IHNlcShtaW4oZ2FtZUluZm8kdmlzaW9uU2NvcmUpLCBtZWFuKGdhbWVJbmZvJHZpc2lvblNjb3JlKSArIDQqc2QoZ2FtZUluZm8kdmlzaW9uU2NvcmUpLCBsZW5ndGgub3V0ID0gNTApLA0KICB5ID0gc2VxKDUsIDYwLCBsZW5ndGgub3V0ID0gNTApLA0KICB6ID0gZGF0YS50ZW1wJHZpc2lvblNjb3JlLnN1cHBvcnQsDQogIHR5cGUgPSAic3VyZmFjZSINCikgJT4lIA0KICBsYXlvdXQoDQogICAgc2NlbmUgPSBsaXN0KA0KICAgICAgeGF4aXMgPSBsaXN0KHRpdGxlID0gIlZpc2lvbiBTY29yZSIpLA0KICAgICAgeWF4aXMgPSBsaXN0KHRpdGxlID0gIkdhbWUgVGltZSAoTWlucykiKSwNCiAgICAgIHpheGlzID0gbGlzdCh0aXRsZSA9ICJQcm9iYWJpbGl0eSBvZiB3aW5uaW5nIikNCiAgICApDQogICkNCg0KcmVzdWx0cyRwbG90cyR2aXNpb25TY29yZS50aW1lLnN1cHBvcnQNCmBgYA0KYGBge3J9DQpyZXN1bHRzJHBsb3RzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydCA8LSBwbG90X2x5KA0KICB4ID0gc2VxKG1pbihnYW1lSW5mbyR2aXNpb25TY29yZSksIG1lYW4oZ2FtZUluZm8kdmlzaW9uU2NvcmUpICsgNCpzZChnYW1lSW5mbyR2aXNpb25TY29yZSksIGxlbmd0aC5vdXQgPSA1MCksDQogIHkgPSBzZXEoNSwgNjAsIGxlbmd0aC5vdXQgPSA1MCksDQogIHogPSBkYXRhLnRlbXAkdmlzaW9uU2NvcmUubm9uU3VwcG9ydCwNCiAgdHlwZSA9ICJzdXJmYWNlIg0KKSAlPiUgDQogIGxheW91dCgNCiAgICBzY2VuZSA9IGxpc3QoDQogICAgICB4YXhpcyA9IGxpc3QodGl0bGUgPSAiVmlzaW9uIFNjb3JlIiksDQogICAgICB5YXhpcyA9IGxpc3QodGl0bGUgPSAiR2FtZSBUaW1lIChNaW5zKSIpLA0KICAgICAgemF4aXMgPSBsaXN0KHRpdGxlID0gIlByb2JhYmlsaXR5IG9mIHdpbm5pbmciKQ0KICAgICkNCiAgKQ0KDQpyZXN1bHRzJHBsb3RzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydA0KYGBgDQojIyBDYWxjdWxhdGluZyB0aGUgQ29udG91ciBvZiA1MCUgV2luIFJhdGUNCmBgYHtyfQ0KZGF0YS50ZW1wJGNvbnRvdXIudmlzaW9uU2NvcmUuc3VwcG9ydCA8LSB0aWJibGUoZ2FtZVRpbWUgPSAxOjEyKjUpICU+JSANCiAgbXV0YXRlKHZpc2lvblNjb3JlID0gKC1yZXN1bHRzJG1vZGVscyR2aXNpb25TY29yZS50aW1lLnN1cHBvcnQkY29lZmZpY2llbnRzW1sxXV0tcmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUudGltZS5zdXBwb3J0JGNvZWZmaWNpZW50c1tbM11dKmdhbWVUaW1lKS8ocmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUudGltZS5zdXBwb3J0JGNvZWZmaWNpZW50c1tbMl1dICsgcmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUudGltZS5zdXBwb3J0JGNvZWZmaWNpZW50c1tbNF1dKmdhbWVUaW1lKSkNCmRhdGEudGVtcCRjb250b3VyLnZpc2lvblNjb3JlLm5vblN1cHBvcnQgPC0gdGliYmxlKGdhbWVUaW1lID0gMToxMio1KSAlPiUgDQogIG11dGF0ZSh2aXNpb25TY29yZSA9ICgtcmVzdWx0cyRtb2RlbHMkdmlzaW9uU2NvcmUudGltZS5ub25TdXBwb3J0JGNvZWZmaWNpZW50c1tbMV1dLXJlc3VsdHMkbW9kZWxzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydCRjb2VmZmljaWVudHNbWzNdXSpnYW1lVGltZSkvKHJlc3VsdHMkbW9kZWxzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydCRjb2VmZmljaWVudHNbWzJdXSArIHJlc3VsdHMkbW9kZWxzJHZpc2lvblNjb3JlLnRpbWUubm9uU3VwcG9ydCRjb2VmZmljaWVudHNbWzRdXSpnYW1lVGltZSkpDQoNCmRhdGEudGVtcCRjb250b3VyLnZpc2lvblNjb3JlLnN1cHBvcnQNCmRhdGEudGVtcCRjb250b3VyLnZpc2lvblNjb3JlLm5vblN1cHBvcnQNCmBgYA0KDQpTbyBmb3IgYSBzdXBwb3J0LCB5b3Ugd2FudCB5b3VyIHZpc2lvbiBzY29yZSB0byBiZSBhcm91bmQgMjUgYXQgMjAgbWludXRlcywgNDUgYXQgMzAgbWludXRlcywgYW5kIDgwIGF0IDQwIG1pbnV0ZXMgdG8gaGF2ZSBhIDUwJSBjaGFuY2Ugb2Ygd2lubmluZy4gRm9yIGEgbm9uLXN1cHBvcnQsIHlvdSB3YW50IHlvdXIgdmlzaW9uIHNjb3JlIHRvIGJlIGFyb3VuZCAxMCBhdCAyMCBtaW51dGVzLCAyMCBhdCAzMCBtaW51dGVzLCBhbmQgMzAgYXQgNDAgbWludXRlcy4NCg0KIyBHb2xkIFBlcmNlbnRhZ2UgYnkgUG9zaXRpb24NCkl0J3MgYSBjb21tb24gaWRlYSB0aGF0IHRoZSBBREMgcm9sZSBoYXMgYmVlbiBjb25zaWRlcmVkIHVzZWxlc3MgZm9yIHRoaXMgc2Vhc29uIC0gbGV0J3Mgc2VlIHdoYXQgdGhlIGRhdGEgaGFzIHRvIHNheSBhYm91dCB0aGF0IQ0KYGBge3J9DQpkYXRhLnRlbXAkZ29sZFBlcmNlbnQgPC0gZ2FtZUluZm8gJT4lIA0KICBncm91cF9ieShtYXRjaCwgd2luKSAlPiUgIyBoZXJlIHdpbiBpcyBqdXN0IHVzZWQgdG8gZ3JvdXAgdGVhbQ0KICBtdXRhdGUodGVhbV9nb2xkID0gc3VtKGdvbGRFYXJuZWQpLCBnb2xkRWFybmVkID0gZ29sZEVhcm5lZCAvIHRlYW1fZ29sZCkgJT4lIA0KICB1bmdyb3VwKCkNCg0KcmVzdWx0cyRtb2RlbHMkZ29sZFBlcmNlbnQgPC0gZ2xtKHdpbiB+IGdvbGRFYXJuZWQqaW5kaXZpZHVhbFBvc2l0aW9uLCBkYXRhID0gZGF0YS50ZW1wJGdvbGRQZXJjZW50ICU+JSBmaWx0ZXIoaW5kaXZpZHVhbFBvc2l0aW9uICE9ICJJbnZhbGlkIiksIGZhbWlseSA9ICJiaW5vbWlhbCIpDQoNCnN1bW1hcnkocmVzdWx0cyRtb2RlbHMkZ29sZFBlcmNlbnQpDQpgYGANCmBgYHtyfQ0KcmVzdWx0cyRwbG90cyRnb2xkUGVyY2VudCA8LSBwbG90X21vZGVsKHJlc3VsdHMkbW9kZWxzJGdvbGRQZXJjZW50LCB0eXBlID0gImludCIpDQoNCnJlc3VsdHMkcGxvdHMkZ29sZFBlcmNlbnQgDQpgYGANClNvIGl0IHdvdWxkIGFwcGVhciB0aGF0IGhhdmluZyB5b3VyIGNhcnJ5IGZlZCBpcyBhY3R1YWxseSBhIHZlcnkgc3Ryb25nIGluZGljYXRvciBvZiB3aW4gcGVyY2VudGFnZS4gU28gd2h5IG1pZ2h0IHBlb3BsZSBiZWxpZXZlIHRoYXQgQURDIGlzIHVzZWxlc3M/IExldCdzIGFkZCB0aWVyIGFzIGEgY292YXJpYXRlIGFuZCBzZWUgd2hhdCB3ZSBzZWUuIChBbHNvIGFzIGEgbm90ZSwgd2lucmF0ZSBkcm9wcyBvZmYgYSBjbGlmZiBpZiBzdXBwb3J0IHN0ZWFscyBhbGwgdGhlIGdvbGQgc28gZ29vZCB0byBrbm93Li4uYXMgYSBzdXBwb3J0IG1haW4pDQojIyBBZGQgdGllcg0KYGBge3J9DQpyZXN1bHRzJG1vZGVscyRnb2xkUGVyY2VudC50aWVyIDwtIGdsbSh3aW5+Z29sZEVhcm5lZCppbmRpdmlkdWFsUG9zaXRpb24qdGllciwgZGF0YSA9IGRhdGEudGVtcCRnb2xkUGVyY2VudCAlPiUgZmlsdGVyKGluZGl2aWR1YWxQb3NpdGlvbiAhPSAiSW52YWxpZCIpLCBmYW1pbHkgPSAiYmlub21pYWwiKQ0KDQpzdW1tYXJ5KHJlc3VsdHMkbW9kZWxzJGdvbGRQZXJjZW50LnRpZXIpDQpgYGANCmBgYHtyfQ0KcmVzdWx0cyRwbG90cyRnb2xkUGVyY2VudC50aWVyIDwtIHBsb3RfbW9kZWwocmVzdWx0cyRtb2RlbHMkZ29sZFBlcmNlbnQudGllciwgdHlwZSA9ICJpbnQiKQ0KDQpyZXN1bHRzJHBsb3RzJGdvbGRQZXJjZW50LnRpZXJbWzRdXQ0KYGBgDQpSZXN1bHRzIGFyZSB1bmNsZWFyLCBmb3IgbG93ZXIgZWxvJ3MgKmluIGdlbmVyYWwqLCBnb2xkIHBlcmNlbnRhZ2UgaXMgbGVzcyBpbXBvcnRhbnQgb24gQURDIGJ1dCBpdCdzIG5vdCBzdXBlciBjbGVhciBiYXNlZCBvbiB0aGUgdGhlIHZhcmlhbmNlIGluIFNpbHZlciBhbmQgUGxhdGludW0uIEludGVyZXN0aW5nbHksIGp1bmdsZSBzZWVtcyB0byBiZSBtb3JlIG9mIGEgY2Fycnkgcm9sZSBpbiBoaWdoZXIgZWxvcy4gTWlnaHQgYmUgYmVjYXVzZSBvZiB0aGUgY2hhbXBpb24gY2hvaWNlLiBUaGlzIHdpbGwgYmUgZXhhbWluZWQgbGF0ZXIuDQoNCiMgVG90YWwgRGFtYWdlIERvbmUNCmBgYHtyfQ0KcmVzdWx0cyRtb2RlbHMkZGFtYWdlRG9uZUNoYW1wIDwtIGdsbSh3aW5+dG90YWxEYW1hZ2VEZWFsdFRvQ2hhbXBpb25zKmluZGl2aWR1YWxQb3NpdGlvbiwgZGF0YSA9IGdhbWVJbmZvLm5vSW52YWxpZCwgZmFtaWx5ID0gImJpbm9taWFsIikNCg0Kc3VtbWFyeShyZXN1bHRzJG1vZGVscyRkYW1hZ2VEb25lQ2hhbXApDQpgYGANCmBgYHtyfQ0KcmVzdWx0cyRwbG90cyRkYW1hZ2VEb25lQ2hhbXAgPC0gcGxvdF9tb2RlbChkYW1hZ2VEb25lQ2hhbXAuZml0LCB0eXBlID0gImludCIpDQoNCnJlc3VsdHMkcGxvdHMkZGFtYWdlRG9uZUNoYW1wDQpgYGANCk5vdCBtdWNoIGRpZmZlcmVuY2UgYmFzZWQgb24gd2hvZXZlciBkb2VzIGRhbWFnZSB0byBjaGFtcGlvbiBhc2lkZSBmcm9tIHN1cHBvcnQuDQojIyBBdmVyYWdlIFRvdGFsIERhbWFnZSBhbmQgRGFtYWdlIHRvIENoYW1waW9ucyBiYXNlZCBvbiBSb2xlDQpgYGB7cn0NCmRhdGEudGVtcCRkYW1hZ2VEb25lIDwtIGdhbWVJbmZvLm5vSW52YWxpZCAlPiUgDQogIHNlbGVjdChpbmRpdmlkdWFsUG9zaXRpb24sIHRvdGFsRGFtYWdlRGVhbHRUb0NoYW1waW9ucywgdG90YWxEYW1hZ2VEZWFsdCkNCmRhdGEudGVtcCRkYW1hZ2VEb25lICU+JSANCiAgZ2dwbG90KGFlcyh4ID0gaW5kaXZpZHVhbFBvc2l0aW9uLCB5ID0gdG90YWxEYW1hZ2VEZWFsdCkpICsNCiAgZ2VvbV9ib3hwbG90KCkNCmRhdGEudGVtcCRkYW1hZ2VEb25lICU+JSAgDQogIGdncGxvdChhZXMoeCA9IGluZGl2aWR1YWxQb3NpdGlvbiwgeSA9IHRvdGFsRGFtYWdlRGVhbHRUb0NoYW1waW9ucykpICsNCiAgZ2VvbV9ib3hwbG90KCkNCmRhdGEudGVtcCRkYW1hZ2VEb25lICU+JSAgDQogIGdyb3VwX2J5KGluZGl2aWR1YWxQb3NpdGlvbikgJT4lIA0KICBzdW1tYXJpemUoYXZnX2RhbWFnZV9jaGFtcCA9IG1lYW4odG90YWxEYW1hZ2VEZWFsdFRvQ2hhbXBpb25zKSwgYXZnX2RhbWFnZV90b3RhbCA9IG1lYW4odG90YWxEYW1hZ2VEZWFsdCkpDQpgYGANCiMjIEtydXNrYWwtV2FsbGlzIFRlc3QNCmBgYHtyfQ0Ka3J1c2thbC50ZXN0KHRvdGFsRGFtYWdlRGVhbHR+aW5kaXZpZHVhbFBvc2l0aW9uLCBkYXRhID0gZGF0YS50ZW1wJGRhbWFnZURvbmUpDQpwYWlyd2lzZS53aWxjb3gudGVzdChkYXRhLnRlbXAkZGFtYWdlRG9uZSR0b3RhbERhbWFnZURlYWx0LCBkYXRhLnRlbXAkZGFtYWdlRG9uZSRpbmRpdmlkdWFsUG9zaXRpb24sIHAuYWRqdXN0Lm1ldGhvZCA9ICJmZHIiKQ0KYGBgDQpOb3QgcmVhbGx5IHVzZWZ1bCwgc2FtcGxlIHNpemUgaXMgc28gbGFyZ2Ugd2hpY2ggbWFrZXMgYW55IHNtYWxsIGRpZmZlcmVuY2Ugc2lnbmlmaWNhbnQuIFZpc3VhbCBhbmFseXNpcyBvZiBib3hwbG90cyBwcm9iYWJseSBtb3JlIHVzZWZ1bC4NCg0KIyBDaGFtcGlvbiBEaWZmaWN1bHR5DQpgYGB7cn0NCmRhdGEudGVtcCRjaGFtcGlvbkRpZmZpY3VsdHkgPC0gZ2FtZUluZm8gJT4lIA0KICBsZWZ0X2pvaW4oDQogICAgY2hhbXBpb25zLnNjcmFwZWQgJT4lIA0KICAgICAgc2VsZWN0KG5hbWUsIGRpZmZpY3VsdHkpLA0KICAgIGJ5ID0gYygiY2hhbXBpb25OYW1lIiA9ICJuYW1lIikNCiAgKSAlPiUgDQogIGZpbHRlcighaXMubmEoZGlmZmljdWx0eSkpDQoNCnJlc3VsdHMkbW9kZWxzJGNoYW1waW9uRGlmZmljdWx0eSA8LSBnbG0od2luIH4gZGlmZmljdWx0eSp0aWVyLCBkYXRhID0gZGF0YS50ZW1wJGNoYW1waW9uRGlmZmljdWx0eSwgZmFtaWx5ID0gImJpbm9taWFsIikNCg0Kc3VtbWFyeShyZXN1bHRzJG1vZGVscyRjaGFtcGlvbkRpZmZpY3VsdHkpDQpgYGANCmBgYHtyfQ0KcmVzdWx0cyRwbG90cyRjaGFtcGlvbkRpZmZpY3VsdHkgPC0gcGxvdF9tb2RlbChyZXN1bHRzJG1vZGVscyRjaGFtcGlvbkRpZmZpY3VsdHksIHR5cGUgPSAiaW50IikNCg0KcmVzdWx0cyRwbG90cyRjaGFtcGlvbkRpZmZpY3VsdHkNCmBgYA0KSGFyZCB0byBzYXkgLSBJIG1pZ2h0IGhhdmUgZXhwZWN0ZWQgdGhhdCB3aW4gcmF0ZSBvZiBkaWZmaWN1bHQgY2hhbXBpb25zIHdvdWxkIGluY3JlYXNlIHdoZW4gd2UgZ2V0IHRvIGhpZ2hlciByYW5rcy4gRGlmZmljdWx0eSBob3dldmVyLCBkb2VzIG5vdCB0YWtlIGludG8gYWNjb3VudCBtZXRhIGFuZCBvdGhlciBpbnRlcmFjdGlvbnMuIFRoZSBtb2RlbCBnZW5lcmF0ZWQgZG9lc24ndCBoYXZlIHRoZSBncmVhdGVzdCBzaWduaWZpY2FuY2Ugc28gaW50ZXJwcmV0YWJpbGl0eSBpcyBsaW1pdGVkLiBJdCBpcyBzdHJpa2luZyBob3dldmVyLCB0aGUgZ2VuZXJhbCB0cmVuZCBvZiB3aW5yYXRlIGRlY3JlYXNpbmcgd2l0aCB0aGUgaW5jcmVhc2Ugb2YgY2hhbXBpb24gZGlmZmljdWx0eS4gTWF5YmUgaWYgd2UgaW50ZXJwcmV0IGRpZmZpY3VsdHkgYXMgYW4gb3JkaW5hbCB2YXJpYWJsZSB3ZSBtaWdodCBzZWUgYSBzaWduaWZpY2FudCBsaW5lYXIgcmVncmVzc2lvbiBtb2RlbC4NCg0KQSBzb2Z0IHRha2Vhd2F5IHRoZW4gaXMgcGxheSBlYXNpZXIgY2hhbXBpb25zLi4uYXQgbGVhc3QgZWFzaWVyIGFzIGRlZmluZWQgYnkgbW9iYWx5dGljcy4NCg==